#include <QDirIterator>
#include <QBrush>
#include <QMimeData>

#include "modelaudiofiles.h"
#include "playlistentry.h"
#include "playlist.h"

#include "debugmodule.h"

const QString ModelAudioFiles::MIME_TYPE = "application/pefc.audiofile";
const QBrush ModelAudioFiles::NOPLAYLIST_BRUSH = QBrush(Qt::red);
const QBrush ModelAudioFiles::MOREPLAYLISTS_BRUSH = QBrush(QColor("orange"));

ModelAudioFiles::ModelAudioFiles(QObject *parent) :
    QAbstractTableModel(parent)
{
}

ModelAudioFiles::~ModelAudioFiles()
{
    qDeleteAll(m_files);
}

int ModelAudioFiles::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;
    else
        return m_files.size();
}

int ModelAudioFiles::columnCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;
    else
        return MaxColIdx;
}

QVariant ModelAudioFiles::data(const QModelIndex &index, int role) const
{
    switch (role)
    {
    case Qt::DisplayRole:
        switch(index.column())
        {
        case Filename:
            return m_files.at(index.row())->filename();
        case NoOfPlaylistEntries:
            return m_files.at(index.row())->entriesCount();
        case Tags:
            return m_files.at(index.row())->tags();
        case Cover:
            return m_files.at(index.row())->hasCover() ?
                        QStringLiteral("Vorhanden") : QStringLiteral("Nicht vorhanden");
        case Lyrics:
            return m_files.at(index.row())->hasLyrics() ?
                        QStringLiteral("Vorhanden") : QStringLiteral("Nicht vorhanden");
        }
        break;

    case Qt::ToolTipRole:
        switch (index.column())
        {
        case Filename:
            return m_files.at(index.row())->fileInfo().absoluteFilePath();
        case NoOfPlaylistEntries:
        {
            QStringList lists;
            const QSet<PlaylistEntry*>& entries = m_files.at(index.row())->entries();
            foreach(PlaylistEntry* entry, entries)
                lists << entry->playlist()->fileInfo().absoluteFilePath();
            qSort(lists);
            return lists.join('\n');
        }
        }
        break;

    case Qt::CheckStateRole:
        switch(index.column())
        {
        case Cover:
            return m_files.at(index.row())->hasCover() ? Qt::Checked : Qt::Unchecked;
        case Lyrics:
            return m_files.at(index.row())->hasLyrics() ? Qt::Checked : Qt::Unchecked;
        }

        break;

    case Qt::TextAlignmentRole:
    {
        const int col = index.column();
        Qt::Alignment alignment = Qt::AlignVCenter;
        alignment |= col == Filename || col == Tags ?
                    Qt::AlignLeft : Qt::AlignRight;
        return QVariant(alignment);
    }

    case Qt::DecorationRole:
        if (index.column() == 0)
            return m_files.at(index.row())->cover();
        break;

    case Qt::BackgroundRole:
        const int noOfLists = m_files.at(index.row())->entriesCount();
        if (noOfLists == 0)
            return NOPLAYLIST_BRUSH;
        else if (noOfLists > 1)
            return MOREPLAYLISTS_BRUSH;
        break;
    }

    return QVariant();
}

QVariant ModelAudioFiles::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
    {
        switch(section)
        {
        case Filename:
            return QStringLiteral("Dateiname");
        case NoOfPlaylistEntries:
            return "Playlisteneinträge";
        case Tags:
            return QStringLiteral("Tags");
        case Cover:
            return QStringLiteral("Cover");
        case Lyrics:
            return QStringLiteral("Lyrics");
        }
    }

    return QVariant();
}

Qt::ItemFlags ModelAudioFiles::flags(const QModelIndex &index) const
{
    const Qt::ItemFlags defaultFlags = QAbstractTableModel::flags(index);

    if (index.isValid())
        return defaultFlags | Qt::ItemIsDragEnabled;
    else
        return defaultFlags;
}

QStringList ModelAudioFiles::mimeTypes() const
{
    static QStringList l(MIME_TYPE);
    return l;
}

QMimeData *ModelAudioFiles::mimeData(const QModelIndexList &indexes) const
{
    QMimeData* data = new QMimeData();
    QByteArray encodedData;

    QDataStream stream(&encodedData, QIODevice::WriteOnly);

    foreach(const QModelIndex& idx, indexes)
    {
        if (idx.isValid() && idx.column() == 0)
        {
            stream << reinterpret_cast<int>(m_files.at(idx.row()));
        }
    }

    data->setData(MIME_TYPE, encodedData);
    return data;
}

int ModelAudioFiles::loadFiles(const QString &i_dir)
{
    beginResetModel();
    qDeleteAll(m_files);
    m_files.clear();
    m_hash.clear();

    if (!i_dir.isEmpty())
    {
        QDirIterator it(i_dir, QStringList("*.mp3"), QDir::Files,
                        QDirIterator::Subdirectories);
        AudioFile* pFile = NULL;

        while(it.hasNext())
        {
            const QString& path = it.next();
            pFile = new AudioFile(path);
            m_files << pFile;
            m_hash.insert(path, pFile);
            connect(pFile, SIGNAL(dataChanged()), SLOT(audioFileChanged()));
        }
    }

    endResetModel();
    return m_files.size();
}

void ModelAudioFiles::audioFileChanged()
{
    if (AudioFile* pFile = qobject_cast<AudioFile*>(sender()))
    {
        const int idx = m_files.indexOf(pFile);

        if (idx > -1)
        {
            emit dataChanged(index(idx,0), index(idx,MaxColIdx - 1));
        }
    }
}

/*void ModelAudioFiles::updateView()
{
    beginResetModel();
    endResetModel();
}*/
